package com.yami.shop.api.controller;


import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yami.shop.bean.dto.WxLoginDTO;
import com.yami.shop.bean.model.User;
import com.yami.shop.bean.param.UserRegisterParam;
import com.yami.shop.bean.vo.wxLoginVO;
import com.yami.shop.common.bean.WeChatProperties;
import com.yami.shop.common.exception.YamiShopBindException;
import com.yami.shop.common.response.ResponseEnum;
import com.yami.shop.common.util.DecryptionUtil;
import com.yami.shop.common.util.HttpClientUtil;
import com.yami.shop.dao.UserMapper;
import com.yami.shop.security.common.bo.UserInfoInTokenBO;
import com.yami.shop.security.common.enums.SysTypeEnum;
import com.yami.shop.security.common.manager.PasswordManager;
import com.yami.shop.security.common.manager.TokenStore;
import com.yami.shop.security.common.vo.TokenInfoVO;
import com.yami.shop.service.UserService;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import lombok.AllArgsConstructor;
import com.yami.shop.common.response.ServerResponseEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.*;

import jakarta.validation.Valid;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 用户信息
 *
 */
@RestController
@RequestMapping("/user")
@Tag(name = "用户注册相关接口")
@AllArgsConstructor
public class UserRegisterController {
    //微信服务接口地址
    private static final String WX_LOGIN ="https://api.weixin.qq.com/sns/jscode2session";

    private WeChatProperties weChatProperties;

    private final UserService userService;

    private final UserMapper userMapper;
    private final PasswordEncoder passwordEncoder;

    private final TokenStore tokenStore;

    private final PasswordManager passwordManager;

    @PostMapping("/register")
    @Operation(summary = "注册" , description = "用户注册或绑定手机号接口")
    public ServerResponseEntity<TokenInfoVO> register(@Valid @RequestBody UserRegisterParam userRegisterParam) {
        if (StrUtil.isBlank(userRegisterParam.getNickName())) {
            userRegisterParam.setNickName(userRegisterParam.getUserName());
        }
        // 正在进行申请注册
        if (userService.count(new LambdaQueryWrapper<User>().eq(User::getNickName, userRegisterParam.getNickName())) > 0) {
            // 该用户名已注册，无法重新注册
            throw new YamiShopBindException("该用户名已注册，无法重新注册");
        }
        Date now = new Date();
        User user = new User();
        user.setModifyTime(now);
        user.setUserRegtime(now);
        user.setStatus(1);
        user.setNickName(userRegisterParam.getNickName());
        user.setUserMail(userRegisterParam.getUserMail());
        String decryptPassword = passwordManager.decryptPassword(userRegisterParam.getPassWord());
        user.setLoginPassword(passwordEncoder.encode(decryptPassword));
        String userId = IdUtil.simpleUUID();
        user.setUserId(userId);
        userService.save(user);
        // 2. 登录
        UserInfoInTokenBO userInfoInTokenBO = new UserInfoInTokenBO();
        userInfoInTokenBO.setUserId(user.getUserId());
        userInfoInTokenBO.setSysType(SysTypeEnum.ORDINARY.value());
        userInfoInTokenBO.setIsAdmin(0);
        userInfoInTokenBO.setEnabled(true);
        return ServerResponseEntity.success(tokenStore.storeAndGetVo(userInfoInTokenBO));
    }


    @PutMapping("/updatePwd")
    @Operation(summary = "修改密码" , description = "修改密码")
    public ServerResponseEntity<Void> updatePwd(@Valid @RequestBody UserRegisterParam userPwdUpdateParam) {
        User user = userService.getOne(new LambdaQueryWrapper<User>().eq(User::getNickName, userPwdUpdateParam.getNickName()));
        if (user == null) {
            // 无法获取用户信息
            throw new YamiShopBindException("无法获取用户信息");
        }
        String decryptPassword = passwordManager.decryptPassword(userPwdUpdateParam.getPassWord());
        if (StrUtil.isBlank(decryptPassword)) {
            // 新密码不能为空
            throw new YamiShopBindException("新密码不能为空");
        }
        String password = passwordEncoder.encode(decryptPassword);
        if (StrUtil.equals(password, user.getLoginPassword())) {
            // 新密码不能与原密码相同
            throw new YamiShopBindException("新密码不能与原密码相同");
        }
        user.setModifyTime(new Date());
        user.setLoginPassword(password);
        userService.updateById(user);
        return ServerResponseEntity.success();
    }
    @PostMapping("/wxLogin")
    @Operation(summary = "微信登陆接口")
    public ServerResponseEntity<TokenInfoVO> wxLogin(@RequestBody @Parameter(name = "微信登陆凭证") WxLoginDTO wxLoginDTO){

        String code = wxLoginDTO.getCode();
        String iv = wxLoginDTO.getIv();
        String encryptedData = wxLoginDTO.getEncryptedData();

        //调用微信接口 获得sessionKey
        Map<String, String> openidAndSessionKey = getOpenidAndSessionKey(code);
        String sessionKey = openidAndSessionKey.get("sessionKey"); //获得sessionKey 秘钥
        String openid = openidAndSessionKey.get("openid");  //获得openid
        String decrypt =null;
        //开始解密获取用户信息
        try {
            decrypt  = DecryptionUtil.decrypt(encryptedData, sessionKey, iv);
        } catch (Exception e) {
        }
        //微信登陆
        //判断openid 是否为空 如果为空表示登录失败，抛出异常
        if (openid==null){
            throw new YamiShopBindException(ResponseEnum.EXCEPTION);
        }
        JSONObject jsonObject = JSON.parseObject(decrypt);
        //判断当前用户是否新用户
        User user = userMapper.getByOpenid(openid);
        //如果是新用户，自动完成注册
        if (user==null){
            user = new User();
            user.setUserId(openid);
            user.setNickName(jsonObject.getString("nickName"));
            user.setPic(jsonObject.getString("avatarUrl"));
            Date now = new Date();
            user.setModifyTime(now);
            user.setUserRegtime(now);
            user.setStatus(1);
            userMapper.insert(user);
        }
        //生成token
        UserInfoInTokenBO userInfoInToken = new UserInfoInTokenBO();
        userInfoInToken.setUserId(user.getUserId());
        userInfoInToken.setSysType(SysTypeEnum.ORDINARY.value());
        userInfoInToken.setEnabled(user.getStatus() == 1);
        // 存储token返回vo
        TokenInfoVO tokenInfoVO = tokenStore.storeAndGetVo(userInfoInToken);
        //返回这个对象
        return ServerResponseEntity.success(tokenInfoVO) ;

    }

    /**
     * 根据code 码 获取 openId
     * @param code
     * @return
     */
    //调用微信接口服务，获得当前微信用户的openId
    private Map<String,String> getOpenidAndSessionKey(String code){
        Map<String, String> map =new HashMap<>();
        map.put("appid",weChatProperties.getAppid());
        map.put("secret",weChatProperties.getSecret());
        map.put("js_code",code);
        map.put("grant_type","authorization_code");
        String json = HttpClientUtil.doGet(WX_LOGIN, map);
        JSONObject jsonObject = JSON.parseObject(json); //将字符串转化为json对象
        String openid = jsonObject.getString("openid");
        Map<String, String> resultMap = new HashMap<>();
        resultMap.put("openid",openid);
        resultMap.put("sessionKey",jsonObject.getString("session_key"));
        return resultMap ;
    }


}
